﻿Imports System.IO
Imports System.Threading
Imports Microsoft.VisualBasic.FileIO

Public Class frmMain
    Private m_CalcTable As DataTable
    Private m_ResistorList As New List(Of Double)
    Private m_TargetValue As Double
    Private m_Progress As Integer

    Private Delegate Sub delegate_complete()
    Private m_complete As New delegate_complete(AddressOf WorkComplete)

    ''' <summary>
    ''' 计算完成后处理
    ''' </summary>
    Private Sub WorkComplete()
        Me.Enabled = True
    End Sub

    ''' <summary>
    ''' 创建计算表
    ''' </summary>
    Private Sub MakeTable()
        m_CalcTable = New DataTable

        Dim col As DataColumn

        col = New DataColumn
        col.ColumnName = "R1"
        col.DataType = GetType(Double)
        col.DefaultValue = 0.0
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "R2"
        col.DataType = GetType(Double)
        col.DefaultValue = 0.0
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "Dvalue"
        col.DataType = GetType(Double)
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "R1阻值"
        col.DataType = GetType(String)
        col.DefaultValue = ""
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "R2阻值"
        col.DataType = GetType(String)
        col.DefaultValue = ""
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "得数"
        col.DataType = GetType(Double)
        m_CalcTable.Columns.Add(col)

        col = New DataColumn
        col.ColumnName = "偏差"
        col.DataType = GetType(Double)
        m_CalcTable.Columns.Add(col)
    End Sub

    ''' <summary>
    ''' 加载常用电阻列表
    ''' </summary>
    Private Sub LoadData()
        Dim n As Double

        m_ResistorList.Clear()

        If File.Exists(Application.StartupPath & "\Resistor.list") Then
            Using RF As New StreamReader(Application.StartupPath & "\Resistor.list")
                While Not RF.EndOfStream
                    Try
                        n = Val(RF.ReadLine)
                        m_ResistorList.Add(n)
                    Catch ex As Exception

                    End Try
                End While
            End Using
        End If
    End Sub

    ''' <summary>
    ''' 转换电阻值为带单位的字符串
    ''' </summary>
    ''' <param name="value"></param>
    ''' <returns></returns>
    Private Function getUnitText(value As Double)
        Dim retStr As String = ""

        If value >= 1000000 Then
            retStr = (value / 1000000).ToString("F2") & "M"
        ElseIf value >= 1000 Then
            retStr = (value / 1000).ToString("F2") & "K"
        Else
            retStr = value.ToString("0")
        End If

        Return retStr
    End Function

    ''' <summary>
    ''' 导出数据
    ''' </summary>
    ''' <param name="FileName"></param>
    Private Sub exportData(FileName As String)
        Dim headers = (From header As DataGridViewColumn In dgElectricResistance.Columns.Cast(Of DataGridViewColumn)()
                       Select header.HeaderText).ToArray
        Dim rows = From row As DataGridViewRow In dgElectricResistance.Rows.Cast(Of DataGridViewRow)()
                   Where Not row.IsNewRow
                   Select Array.ConvertAll(row.Cells.Cast(Of DataGridViewCell).ToArray, Function(c) If(c.Value IsNot Nothing, c.Value.ToString, ""))
        Using sw As New IO.StreamWriter(FileName, False, System.Text.Encoding.Unicode)
            sw.WriteLine(String.Join(",", headers))
            For Each r In rows
                sw.WriteLine(String.Join(",", r))
            Next
        End Using
    End Sub

    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Icon = My.Resources.Resistor
        txtFormula.Text = My.Settings.Formula
        txtTarget.Text = My.Settings.Target
        numMin.Value = My.Settings.MinValue
        numMax.Value = My.Settings.MaxValue
        '设置界面字体
        Me.Font = New Font(My.Settings.FontName, My.Settings.FontSize)
        LoadData()
    End Sub

    Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
        Dim calc_result As Double

        m_TargetValue = Val("0" & txtTarget.Text)

        Me.Enabled = False
        txtFormula.Text = txtFormula.Text.ToUpper()
        My.Settings.Formula = txtFormula.Text
        My.Settings.Target = txtTarget.Text
        My.Settings.MinValue = numMin.Value
        My.Settings.MaxValue = numMax.Value

        MakeTable()

        Try
            calc_result = m_CalcTable.Compute(txtFormula.Text.Replace("R1", "1").Replace("R2", "1"), String.Empty)
        Catch ex As Exception
            MsgBox("计算表达式不正确", MsgBoxStyle.Critical, "错误")
            WorkComplete()
            Exit Sub
        End Try

        m_CalcTable.Rows.Clear()
        m_CalcTable.Columns("Dvalue").Expression = String.Format("{0}-({1})", txtTarget.Text, txtFormula.Text)
        m_CalcTable.Columns("得数").Expression = txtFormula.Text


        '尝试电阻组合
        For Each r1 As Double In m_ResistorList
            For Each r2 As Double In m_ResistorList
                If (r1 >= numMin.Value AndAlso r1 <= numMax.Value) AndAlso (r2 >= numMin.Value AndAlso r2 <= numMax.Value) Then
                    Dim row As DataRow

                    row = m_CalcTable.NewRow

                    row("R1") = r1
                    row("R2") = r2
                    m_CalcTable.Rows.Add(row)
                End If
            Next
        Next

        m_CalcTable.AcceptChanges()

        Dim temp_view As New DataView(m_CalcTable)

        dgElectricResistance.AutoGenerateColumns = False
        dgElectricResistance.DataSource = temp_view
        '填充显示列数据
        For Each row As DataRow In m_CalcTable.Rows
            row("偏差") = Math.Abs(row("Dvalue"))
            row("R1阻值") = getUnitText(row("R1"))
            row("R2阻值") = getUnitText(row("R2"))
        Next
        temp_view.Sort = "偏差 ASC"
        WorkComplete()
        MsgBox("计算完成", MsgBoxStyle.Information, "信息")
        dgElectricResistance.Refresh()
    End Sub

    Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
        If dgElectricResistance.Rows.Count > 0 Then
            sfdSaveData.Title = "导出数据"
            sfdSaveData.FileName = Now.ToString("yyyyMMdd_HHmmss") & "_电阻选择表.csv"
            If sfdSaveData.ShowDialog = DialogResult.OK Then
                exportData(sfdSaveData.FileName)
            End If
        End If
    End Sub

End Class